package com.lh.controller;

import com.lh.model.User;
import com.lh.service.FileService;
import com.lh.util.MyException;
import com.lh.util.MyLog;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.file.Files;

/**
 * @Author LuoHang
 * @Date 2022-05-10 22:34
 **/
@Controller
@RequestMapping("/file")
public class FileController {
    @Value("${uploadFolder}")
    private String uploadFolder;

    @Resource(name = "fileServiceImpl")
    private FileService fileService;

    /**
     * 单个文件上传+数据接收
     * @param model 数据模型
     * @param user 对象
     * @param multipartFile 文件形参对象
     * @return 视图
     * @throws MyException 自定义异常
     */
    @PostMapping("/upload")
    public String upload(Model model,User user, @RequestPart("oneFile") MultipartFile multipartFile) throws MyException{
        MyLog.info(FileController.class,"开始执行文件上传" + user.getId());
        String filename = System.currentTimeMillis() + multipartFile.getOriginalFilename();
        String path = uploadFolder + filename;
        File file = new File(path);
        if (!file.exists()){
            MyLog.info(FileController.class,file.mkdirs() ? "创建成功：" + path : "创建失败");
        }
        try {
            multipartFile.transferTo(file);
            if(!fileService.upload(new com.lh.model.File(null, path, filename, user.getId()))){
                throw new MyException("文件上传失败");
            }
        } catch (IOException e) {
            MyLog.info(FileController.class,e.getMessage());
            //抛送给全局Controller异常处理类处理
            throw new MyException("文件上传失败");
        }
        model.addAttribute("path","upload/file" + File.separator + filename);
        return "index";
    }

    /**
     * 多文件上传+数据传送
     * @param uploadFiles 多文件对象
     * @param uid 用户id
     * @param request 请求对象
     * @return 上传信息
     */
    @PostMapping("/uploads")
    public @ResponseBody String uploads(@RequestParam("files") MultipartFile[] uploadFiles,
                                        @RequestParam("id") Integer uid,HttpServletRequest request){
        for (MultipartFile uploadFile : uploadFiles) {
            String filename = System.currentTimeMillis() + uploadFile.getOriginalFilename();
            String path = uploadFolder + File.separator + filename;
            File file = new File(path);
            if (!file.exists()){
                MyLog.info(FileController.class,file.mkdirs() ? "创建成功：" + path : "创建失败");
            }
            try {
                uploadFile.transferTo(file);
                fileService.upload(new com.lh.model.File(null, path, filename, uid));
            } catch (IOException e) {
                MyLog.info(FileController.class,e.getMessage());
                return "上传失败";
            }
        }
        return "上传成功";
    }

    /**
     * 文件下载
     * @param id 文件id
     * @param response 响应对象
     * @throws MyException 自定义异常
     */
    @GetMapping("/downLoad")
    public void downLoad(Integer id,HttpServletResponse response) throws MyException{
        com.lh.model.File poj = fileService.getFileById(id);
        //通过文件的保存文件夹路径加上文件的名字来获得文件
        File file = new File(poj.getUrl());
        //当文件存在
        if(file.exists()){
            //首先设置响应的内容格式是force-download，那么你一旦点击下载按钮就会自动下载文件了
            response.setContentType("application/force-download");
            //通过设置头信息给文件命名。在前端，文件流被接受完后，下载生成的文件会以你传递的文件名来命名
            response.addHeader("Content-Disposition",String.format("attachment; filename=\"%s\"", file.getName()));
            //进行读写操作
            byte[] buffer = new byte[1024];
            try(BufferedInputStream bis = new BufferedInputStream(Files.newInputStream(file.toPath()))){
                OutputStream os = response.getOutputStream();
                //从源文件中读
                int i = bis.read(buffer);
                while(i != -1){
                    //写到response的输出流中
                    os.write(buffer,0,i);
                    i = bis.read(buffer);
                }
                os.flush();
                os.close();
            }catch (IOException e){
                throw new MyException(e.getMessage());
            }
        }
    }
}
